package io.pumelo.noti.handler;

import com.alibaba.fastjson.JSON;
import com.alibaba.fastjson.JSONObject;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.pumelo.noti.abstructhandler.AbstractNotiHandler;
import io.pumelo.noti.client.NettyClient;
import io.pumelo.noti.common.LOG;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

@Component
@ChannelHandler.Sharable
public class EventHandler extends SimpleChannelInboundHandler<String> {
    /**noti2.0 收到事件回复格式*/
    static final String ACK = "{\"cmd\":\"event_ack\",\"delivery_id\":deliveryId}\n";

    @Autowired
    private AbstractNotiHandler handler;

    @Autowired
    private NettyClient nettyClient;

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        LOG.warn(this,"channel is inactive.");
        nettyClient.destroy();
        LOG.warn(this,"need reconnect");
        nettyClient.init();
        super.channelInactive(ctx);
    }

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
        LOG.info(this,"channelMsg:" + msg);
        JSONObject object = JSON.parseObject(msg);
        String cmd = object.getString("cmd");
        switch (cmd) {
            case "login_res":
                handleLoginRes(object, ctx);
                break;
            case "pong":
                handlePong();
                break;
            case "event_push":
                handleEventPush(object, ctx);
                break;
            case "invalid_msg":
                handleInvalidMsg(object);
                break;
            default:
                LOG.error(this,"default:" + msg);
        }
    }

    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
        LOG.error(this,"exceptionCaught",cause);
        ctx.close();
    }

    /**
     * 处理登录事件
     * @param object
     * @param ctx
     */
    private void handleLoginRes(JSONObject object, ChannelHandlerContext ctx) {
        handler.handleLoginRes(object);
        JSONObject data = object.getJSONObject("data");
        boolean result = data.getBooleanValue("result");
        //登录成功就开启心跳保障
        if (result) {
            LOG.info(this,"login success");
            //开始心跳检查
            nettyClient.startHeartBeat(ctx);
        }
        //解锁初始化连接能力
        nettyClient.unLock();
    }

    private void handlePong() {
        nettyClient.setLastHeartBeatTime(System.currentTimeMillis());
    }

    private void handleEventPush(JSONObject object, ChannelHandlerContext ctx) {
        String ackStr = ACK.replace("deliveryId", object.getString("delivery_id"));
        //有需要回复的情况
        ctx.writeAndFlush(ackStr);
        try {
            String event_type = object.getString("event_type");
            switch (event_type) {
                case "device_offline":
                    handler.handleOffline(object);
                    break;
                case "device_online":
                    handler.handleOnline(object);
                    break;
                case "device_status_kv":
                    handler.handleStatusKV(object);
                    break;
                case "device_status_raw":
                    handler.handleStatusRaw(object);
                    break;
                default:
                    break;
            }
        } catch (Exception e) {
            LOG.error(this,"解析异常",e);
        }

    }

    private void handleInvalidMsg(JSONObject object) {
        handler.handleInvalidMsg(object);
    }

}

